home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / bashsrc.zoo / variables.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-05  |  24.5 KB  |  1,039 lines

  1. /* variables.c -- Functions for hacking shell variables. */
  2.  
  3. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7. Bash is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 1, or (at your option) any later
  10. version.
  11.  
  12. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with Bash; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <pwd.h>
  24.  
  25. #include "shell.h"
  26. #include "flags.h"
  27. #include "version.h"
  28.  
  29. #ifdef SYSV
  30. struct passwd *getpwuid (), *getpwent ();
  31. #endif
  32.  
  33. /* The list of shell variables that the user has created, or that came from
  34.    the environment. */
  35. SHELL_VAR *variable_list;
  36.  
  37. /* The current variable context.  This is really a count of how deep into
  38.    executing functions we are. */
  39. int variable_context = 0;
  40.  
  41. /* The array of shell assignments which are made only in the environment
  42.    for a single command. */
  43. char **temporary_env = (char **)NULL;
  44.  
  45. /* Some funky variables which are known about specially.  Here is where
  46.    "$*", "$1", and all the cruft is kept. */
  47. char *dollar_vars[10];
  48. WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
  49.  
  50. /* The value of $$. */
  51. int dollar_dollar_pid;
  52.  
  53. /* An array which is passed to commands as their environment.  It is
  54.    manufactured from the overlap of the initial environment and the
  55.    shell variables that are marked for export. */
  56. char **export_env = (char **)NULL;
  57.  
  58. /* Non-zero means that we have to remake EXPORT_ENV. */
  59. int array_needs_making = 1;
  60.  
  61. /* The list of variables that may not be unset in this shell. */
  62. char **non_unsettable_vars = (char **)NULL;
  63.  
  64. #ifdef SYSV
  65. #define DEFAULT_MAIL_PATH "/usr/mail/"
  66. #else
  67. #define DEFAULT_MAIL_PATH "/usr/spool/mail/"
  68. #endif
  69.  
  70. /* Initialize the shell variables from the current environment. */
  71. initialize_shell_variables (env)
  72.      char *env[];
  73. {
  74.   extern char *primary_prompt, *secondary_prompt;
  75.   char *name, *string;
  76.   int c, char_index;
  77.   int string_index = 0;
  78.   SHELL_VAR *temp_var;
  79.  
  80.   while (string = env[string_index++])
  81.     {
  82.       char_index = 0;
  83.  
  84.       name = (char *)alloca (1 + strlen (string));
  85.  
  86.       while ((c = *string++) && c != '=')
  87.     name[char_index++] = c;
  88.  
  89.       name[char_index] = '\0';
  90.  
  91.       /* If exported function, define it now.  Sigh. */
  92.       if (strncmp ("() {", string, 4) == 0)
  93.     {
  94.       char *eval_string =
  95.         (char *)xmalloc (3 + strlen (string) + strlen (name));
  96.       sprintf (eval_string, "%s %s", name, string);
  97.       parse_and_execute (eval_string, name);
  98.     }
  99.       else
  100.     bind_variable (name, string);
  101.  
  102.       set_var_auto_export (name);
  103.     }
  104.  
  105.   /* Remember this pid. */
  106.   dollar_dollar_pid = getpid ();
  107.  
  108.   /* Now make our own defaults in case the vars that we think are
  109.      important are missing. */
  110.   set_if_not ("PATH", DEFAULT_PATH_VALUE);
  111.   set_var_auto_export ("PATH");
  112.  
  113.   set_if_not ("TERM", "dumb");
  114.   set_var_auto_export ("TERM");
  115.     
  116.   set_if_not ("PS1", primary_prompt);
  117.   set_if_not ("PS2", secondary_prompt);
  118.   set_if_not ("IFS", " \t\n");
  119.  
  120.   /* Magic machine types.  Pretty convenient. */
  121.   bind_variable ("HOSTTYPE", HOSTTYPE);
  122.  
  123.   /* Default MAILPATH, and MAILCHECK. */
  124.   set_if_not ("MAILCHECK", "60");
  125.   if ((get_string_value ("MAIL") == (char *)NULL) &&
  126.       (get_string_value ("MAILPATH") == (char *)NULL))
  127.     {
  128.       extern char *current_user_name;
  129.       char *tem;
  130.  
  131.       tem = (char *)xmalloc (1 + sizeof (DEFAULT_MAIL_PATH)
  132.                + strlen (current_user_name));
  133.       strcpy (tem, DEFAULT_MAIL_PATH);
  134.       strcat (tem, current_user_name);
  135.  
  136.       bind_variable ("MAILPATH", tem);
  137.       free (tem);
  138.     }
  139.  
  140.   /* Set up $PWD. */
  141.   {
  142.     char *get_working_directory (), *cd;
  143.  
  144.     cd = get_working_directory ("shell-init");
  145.     if (cd)
  146.       {
  147.     bind_variable ("PWD", cd);
  148.     free (cd);
  149.       }
  150.   }
  151.   
  152.   /* Do some things with shell level. */
  153.   {
  154.     extern int shell_level;
  155.     char new_level[10];
  156.     int old_level;
  157.  
  158.     set_if_not ("SHLVL", "0");
  159.     set_var_auto_export ("SHLVL");
  160.  
  161.     sscanf (get_string_value ("SHLVL"), "%d", &old_level);
  162.     shell_level = old_level + 1;
  163.     sprintf (new_level, "%d", shell_level);
  164.     bind_variable ("SHLVL", new_level);
  165.   }
  166.  
  167.   /* Get the full pathname to THIS shell, and set the BASH variable
  168.      to it. */
  169.   {
  170.     extern char *shell_name, *find_user_command (), *full_pathname ();
  171.     extern int login_shell;
  172.     char *tname = find_user_command (shell_name);
  173.     
  174.     if ((login_shell == 1) && (*shell_name != '/'))
  175.       {
  176.     struct passwd *entry = getpwuid (getuid ());
  177.  
  178.     if (entry)
  179.       {
  180.         /* If HOME doesn't exist, set it. */
  181.         temp_var = (SHELL_VAR *)find_variable ("HOME");
  182.         if (!temp_var)
  183.           {
  184.         temp_var = bind_variable ("HOME", entry->pw_dir);
  185.         temp_var->attributes |= att_exported;
  186.           }
  187.         name = savestring (entry->pw_shell);
  188.       }
  189.     else
  190.       name = savestring ("a.out");
  191.       }
  192.     else
  193.       {
  194.     if (!tname)
  195.       {
  196.         char *make_absolute ();
  197.         name = make_absolute (shell_name, get_string_value ("PWD"));
  198.       }
  199.     else
  200.       {
  201.         name = full_pathname (tname);
  202.         free (tname);
  203.       }
  204.       }
  205.  
  206.     /* Make the exported environment variable SHELL be whatever the name of
  207.        this shell is.  Note that the `tset' command looks at this variable
  208.        to determine what style of commands to output; if it ends in "csh",
  209.        then C-shell commands are output, else Bourne shell commands. */
  210.     set_if_not ("SHELL", name);
  211.     set_var_auto_export ("SHELL");
  212.  
  213.     /* Make a variable called BASH, which is the name of THIS shell. */
  214.     temp_var = bind_variable ("BASH", name);
  215.     temp_var->attributes |= att_exported;
  216.  
  217.     free (name);
  218.   }
  219.  
  220.   /* Make a variable called BASH_VERSION which contains the version info. */
  221.   {
  222.     char tt[12];
  223.     extern char *dist_version;
  224.     extern int build_version;
  225.  
  226.     sprintf (tt, "%s.%d", dist_version, build_version);
  227.     bind_variable ("BASH_VERSION", tt);
  228.   }
  229.  
  230.   /* Set history variables to defaults, and then do whatever we would
  231.      do if the variable had just been set. */
  232.   {
  233.     char *tilde_expand ();
  234.     char *tem = tilde_expand ("~/.bash_history");
  235.  
  236.     set_if_not ("HISTFILE", tem);
  237.     free (tem);
  238.  
  239.     set_if_not ("HISTSIZE", "500");
  240.     sv_histsize ("HISTSIZE");
  241.   }
  242.  
  243.   /* Gee, might as well get parent pid. */
  244.   {
  245.     char aval[10];
  246.  
  247.     sprintf (aval, "%d", getppid ());
  248.     bind_variable ("PPID", aval);
  249.   }
  250.  
  251.   non_unsettable ("PATH");
  252.   non_unsettable ("PS1");
  253.   non_unsettable ("PS2");
  254.   non_unsettable ("IFS");
  255.  
  256.   /* Get the users real user id, and save that in an readonly variable.
  257.      To make the variable *really* readonly, we have added it to a special
  258.      list of vars. */
  259.  
  260.   sv_uids ();
  261.   set_var_read_only ("UID");
  262.   set_var_read_only ("EUID");
  263.  
  264.   non_unsettable ("EUID");
  265.   non_unsettable ("UID");
  266. }
  267.  
  268. /* Add NAME to the list of variables that cannot be unset
  269.    if it isn't already there. */
  270. non_unsettable (name)
  271.      char *name;
  272. {
  273.   register int i;
  274.  
  275.   if (!non_unsettable_vars)
  276.     {
  277.       non_unsettable_vars = (char **)xmalloc (1 * sizeof (char *));
  278.       non_unsettable_vars[0] = (char *)NULL;
  279.     }
  280.  
  281.   for (i = 0; non_unsettable_vars[i]; i++)
  282.     if (strcmp (non_unsettable_vars[i], name) == 0)
  283.       return;
  284.  
  285.   non_unsettable_vars =
  286.     (char **)xrealloc (non_unsettable_vars, (2 + i) * sizeof (char *));
  287.   non_unsettable_vars[i] = savestring (name);
  288.   non_unsettable_vars[i + 1] = (char *)NULL;
  289. }
  290.  
  291. /* Set NAME to VALUE if NAME has no value. */
  292. set_if_not (name, value)
  293.      char *name, *value;
  294. {
  295.   char *temp = get_string_value (name);
  296.  
  297.   if (!temp)
  298.     bind_variable (name, value);
  299. }
  300.  
  301. /* Print LIST (a linked list of shell variables) to stdout
  302.    in such a way that they can be read back in. */
  303. print_var_list (list)
  304.      register SHELL_VAR *list;
  305. {
  306.   while (list)
  307.     {
  308.       if (!invisible_p (list))
  309.     print_assignment (list);
  310.       list = list->next;
  311.     }
  312. }
  313.  
  314. /* Print the value of a single SHELL_VAR.  No newline is
  315.    output, but the variable is printed in such a way that
  316.    it can be read back in. */
  317. print_assignment (var)
  318.      SHELL_VAR *var;
  319. {
  320.   if (var->value)
  321.     {
  322.       printf ("%s=", var->name);
  323.       print_var_value (var);
  324.       printf ("\n");
  325.     }
  326.  
  327.   if (var->function)
  328.     {
  329.       printf ("%s=", var->name);
  330.       print_var_function (var);
  331.       printf ("\n");
  332.     }
  333. }
  334.  
  335. /* Print the value cell of VAR, a shell variable.  Do not print
  336.    the name, nor leading/trailing newline. */
  337. print_var_value (var)
  338.      SHELL_VAR *var;
  339. {
  340.   if (var->value)
  341.     printf ("%s", var->value);
  342. }
  343.  
  344. /* Print the function cell of VAR, a shell variable.  Do not
  345.    print the name, nor leading/trailing newline. */
  346. print_var_function (var)
  347.      SHELL_VAR *var;
  348. {
  349.   char *named_function_string ();
  350.  
  351.   if (var->function)
  352.     printf ("%s", named_function_string ((char *)NULL, var->function, 1));
  353. }
  354.  
  355. /* Look up the variable entry whose name matches STRING.
  356.    Returns the entry or NULL. */
  357. SHELL_VAR *
  358. find_variable (string)
  359.      char *string;
  360. {
  361.   register SHELL_VAR *list = variable_list;
  362.  
  363.   while (list)
  364.     {
  365.       if (strcmp (string, list->name) == 0)
  366.     return (list);
  367.  
  368.       list = list->next;
  369.     }
  370.   return ((SHELL_VAR *)NULL);
  371. }
  372.  
  373. /* Return the string value of a variable.  Return NULL if the variable
  374.    doesn't exist, or only has a function as a value.  Don't cons a new
  375.    string. */
  376. char *
  377. get_string_value (var_name)
  378.      char *var_name;
  379. {
  380.   SHELL_VAR *var = find_variable (var_name);
  381.  
  382.   if (!var)
  383.     return (char *)NULL;
  384.   else
  385.     return (var->value);
  386. }
  387.  
  388. /* Create a local variable referenced by NAME. */
  389. SHELL_VAR *
  390. make_local_variable (name)
  391.      char *name;
  392. {
  393.   SHELL_VAR *new_var, *old_var, *bind_variable ();
  394.   int var_has_name ();
  395.  
  396.   /* local foo; local foo;  is a no-op. */
  397.   {
  398.     old_var = find_variable (name);
  399.     if (old_var && old_var->context == variable_context)
  400.       return (old_var);
  401.   }
  402.  
  403.   old_var = (SHELL_VAR *)delete_element (&variable_list, var_has_name, name);
  404.  
  405.   /* If a variable does not already exist with this name, then
  406.      just make a new one. */
  407.   if ((int)old_var == -1)
  408.     {
  409.       new_var = bind_variable (name, "");
  410.     }
  411.   else
  412.     {
  413.       new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  414.  
  415.       new_var->name = savestring (name);
  416.       new_var->value = savestring ("");
  417.       new_var->function = (char *)copy_command (old_var->function);
  418.  
  419.       new_var->attributes = 0;
  420.  
  421.       if (exported_p (old_var))
  422.     new_var->attributes |= att_exported;
  423.  
  424.       new_var->prev_context = old_var;
  425.       new_var->next = variable_list;
  426.       variable_list = new_var;
  427.     }
  428.  
  429.   new_var->context = variable_context;
  430.   return (new_var);
  431. }
  432.  
  433. /* Bind a variable name to some string.  This conses up the name
  434.    and value strings. */
  435. SHELL_VAR *
  436. bind_variable (name, value)
  437.      char *name, *value;
  438. {
  439.   SHELL_VAR *entry = find_variable (name);
  440.  
  441.   
  442.   if (!entry)
  443.     {
  444.       /* Make a new entry for this variable.  Then do the binding. */
  445.       entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  446.  
  447.       entry->attributes = 0;
  448.  
  449.       entry->name = savestring (name);
  450.  
  451.       if (value)
  452.     entry->value = savestring (value);
  453.       else
  454.     entry->value = (char *)NULL;
  455.  
  456.       entry->function = (char *)NULL;
  457.  
  458.       entry->next = variable_list;
  459.  
  460.       /* Always assume variables are to be made at toplevel!
  461.      make_local_variable has the responsibilty of changing the
  462.      variable context. */
  463.       entry->context = 0;
  464.       entry->prev_context = (SHELL_VAR *)NULL;
  465.       variable_list = entry;
  466.     }
  467.   else
  468.     {
  469.       if (readonly_p (entry))
  470.     {
  471.       report_error ("%s: read-only variable", name);
  472.       return (entry);
  473.     }
  474.  
  475.       if (entry->value)
  476.     free (entry->value);
  477.  
  478.       if (value)
  479.     entry->value = savestring (value);
  480.       else
  481.     entry->value = (char *)NULL;
  482.     }
  483.  
  484.   if (mark_modified_vars)
  485.     entry->attributes |= att_exported;
  486.  
  487.   if (exported_p (entry))
  488.     array_needs_making = 1;
  489.  
  490.   return (entry);
  491. }
  492.  
  493. /* Dispose of the information attached to a variable. */
  494. dispose_variable (var)
  495.      SHELL_VAR *var;
  496. {
  497.   if (!var)
  498.     return;
  499.  
  500.   if (var->function)
  501.     dispose_command (var->function);
  502.  
  503.   if (var->value)
  504.     free (var->value);
  505.  
  506.   free (var->name);
  507.  
  508.   if (exported_p (var))
  509.     array_needs_making = 1;
  510.  
  511.   free (var);
  512. }
  513.  
  514. /* Return 1 if VAR (a variable) is named NAME (a string). */
  515. var_has_name (var, name)
  516.      SHELL_VAR *var;
  517.      char *name;
  518. {
  519.   if (var)
  520.     return ((strcmp (var->name, name) == 0));
  521.   else
  522.     return (0);
  523. }
  524.  
  525. /* Unbind the function cell of a variable.  If the variable has
  526.    no function cell, then discard it.  Return -1 if the variable
  527.    couldn't be found. */
  528. unbind_function (name)
  529.      char *name;
  530. {
  531.   SHELL_VAR *var = find_variable (name);
  532.  
  533.   if (!var)
  534.     return (-1);
  535.  
  536.   if (var->function)
  537.     {
  538.       dispose_command (var->function);
  539.       var->function = (char *)NULL;
  540.     }
  541.  
  542.   if (!var->value)
  543.     makunbound (name);
  544.  
  545.   return (0);
  546. }
  547.  
  548. /* Unbind the value cell of a variable.  If the variable has
  549.    no value cell, then discard it.  Return -1 if the variable
  550.    couldn't be found. */
  551. unbind_variable (name)
  552.      char *name;
  553. {
  554.   SHELL_VAR *var = find_variable (name);
  555.  
  556.   if (!var)
  557.     return (-1);
  558.  
  559.   if (var->value)
  560.     {
  561.       free (var->value);
  562.       var->value = (char *)NULL;
  563.     }
  564.  
  565.   if (!var->function)
  566.     makunbound (name);
  567.  
  568.   return (0);
  569. }
  570.  
  571. /* Make the variable associated with NAME go away.
  572.    Return non-zero if the variable couldn't be found. */
  573. makunbound (name)
  574.      char *name;
  575. {
  576.   SHELL_VAR *elt = 
  577.     (SHELL_VAR *)delete_element (&variable_list, var_has_name, name);
  578.  
  579.   if ((int)elt != -1)
  580.     {
  581.       if (elt->prev_context)
  582.     {
  583.       SHELL_VAR *new = elt->prev_context;
  584.       new->next = variable_list;
  585.       variable_list = new;
  586.     }
  587.       if (exported_p (elt))
  588.     set_var_auto_export (elt->name);
  589.  
  590.       dispose_variable (elt);
  591.       return (0);
  592.     }
  593.   return (-1);
  594. }
  595.  
  596. /* Remove the variable with NAME if it is a local variable in the
  597.    current context. */
  598. kill_local_variable (name)
  599.      char *name;
  600. {
  601.   SHELL_VAR *temp = find_variable (name);
  602.  
  603.   if (temp && (temp->context == variable_context))
  604.     {
  605.       makunbound (name);
  606.       return (0);
  607.     }
  608.   return (-1);
  609. }
  610.  
  611. /* Get rid of all of the variables in the current context. */
  612. kill_all_local_variables ()
  613. {
  614.   register SHELL_VAR *list = variable_list;
  615.   register SHELL_VAR *prev = (SHELL_VAR *)NULL;
  616.  
  617.   while (list)
  618.     {
  619.       if (list->context && list->context == variable_context)
  620.     {
  621.  
  622.       if (list->prev_context)
  623.         list->prev_context->next = list->next;
  624.       else
  625.         list->prev_context = list->next;
  626.  
  627.       if (prev)
  628.         {
  629.           prev->next = list->prev_context;
  630.           dispose_variable (list);
  631.           list = prev;
  632.         }
  633.       else
  634.         {
  635.           variable_list = list->prev_context;
  636.           dispose_variable (list);
  637.           list = variable_list;
  638.         }
  639.     }
  640.       prev = list;
  641.       list = list->next;
  642.     }
  643. }
  644.  
  645. /* Do a function binding to a variable.  You pass the name and
  646.    the command to bind to.  This conses the name and command. */
  647. SHELL_VAR *
  648. bind_function (name, value)
  649.      char *name;
  650.      COMMAND *value;
  651. {
  652.   SHELL_VAR *entry = find_variable (name);
  653.  
  654.   if (!entry)
  655.     {
  656.       entry = bind_variable (name, "");
  657.       free (entry->value);
  658.       entry->value = (char *)NULL;
  659.     }
  660.  
  661.   if (entry->function)
  662.     dispose_command (entry->function);
  663.  
  664.   entry->function = (char *)copy_command (value);
  665.  
  666.   entry->attributes |= att_function;
  667.  
  668.   if (mark_modified_vars)
  669.     entry->attributes |= att_exported;
  670.  
  671.   array_needs_making = 1;
  672.  
  673.   return (entry);
  674. }
  675.  
  676. /* Copy VAR to a new data structure and return that structure. */
  677. SHELL_VAR *
  678. copy_variable (var)
  679.      SHELL_VAR *var;
  680. {
  681.   SHELL_VAR *copy = (SHELL_VAR *)NULL;
  682.  
  683.   if (var)
  684.     {
  685.       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  686.   
  687.       copy->attributes = var->attributes;
  688.       copy->name = savestring (var->name);
  689.  
  690.       if (var->function)
  691.     copy->function = (char *)copy_command (var->function);
  692.  
  693.       if (var->value)
  694.     copy->value = savestring (var->value);
  695.       else
  696.     copy->value = (char *)NULL;
  697.  
  698.       copy->context = var->context;
  699.  
  700.       /* Don't bother copying previous contexts along with this variable. */
  701.       copy->prev_context = (SHELL_VAR *)NULL;
  702.     }
  703.  
  704.   return (copy);
  705. }
  706.  
  707. /* Make the variable associated with NAME be read-only.
  708.    If NAME does not exist yet, create it. */
  709. set_var_read_only (name)
  710.      char *name;
  711. {
  712.   SHELL_VAR *entry = find_variable (name);
  713.  
  714.   if (!entry)
  715.     {
  716.       entry = bind_variable (name, "");
  717.       if (!no_invisible_vars)
  718.     entry->attributes |= att_invisible;
  719.     }
  720.   entry->attributes |= att_readonly;
  721. }
  722.  
  723. /* Make the variable associated with NAME be auto-exported.
  724.    If NAME does not exist yet, create it. */
  725. set_var_auto_export (name)
  726.      char *name;
  727. {
  728.   SHELL_VAR *entry = find_variable (name);
  729.   
  730.   if (!entry)
  731.     {
  732.       entry = bind_variable (name, "");
  733.       if (!no_invisible_vars)
  734.     entry->attributes |= att_invisible;
  735.     }
  736.   entry->attributes |= att_exported;
  737.   array_needs_making = 1;
  738. }
  739.  
  740. /* Returns non-zero if STRING is an assignment statement.  The returned value
  741.    is the index of the `=' sign. */
  742. assignment (string)
  743.      char *string;
  744. {
  745.   register int c, index = 0;
  746.  
  747.   c = string[index];
  748.   if (!isletter (c) && c != '_')
  749.     return (0);
  750.  
  751.   while (c = string[index])
  752.     {
  753.       /* The following is safe.  Note that '=' at the start of a word
  754.      is not an assignment statement. */
  755.       if (c == '=')
  756.     return (index);
  757.  
  758.       if (!isletter (c) && !digit (c) && c != '_')
  759.     return (0);
  760.  
  761.       index++;
  762.     }
  763.   return (0);
  764. }
  765.  
  766. /* Make an array out of LIST, a list of SHELL_VAR.  Only visible
  767.    variables which are marked for export are eligible. */
  768. char **
  769. make_var_array (list)
  770.      SHELL_VAR *list;
  771. {
  772.   register int count = 0;
  773.   register char **array;
  774.   register SHELL_VAR *head = list;
  775.   int hack_it_twice = 0;
  776.  
  777.   while (list)
  778.     {
  779.       if (exported_p (list) && !invisible_p (list))
  780.     {
  781.       if (list->function)
  782.         count++;
  783.  
  784.       if (list->value)
  785.         count++;
  786.     }
  787.       list = list->next;
  788.     }
  789.  
  790.   array = (char **)xmalloc ((1 + count) * sizeof (char *));
  791.   list = head;
  792.   count = 0;
  793.  
  794.   while (list)
  795.     {
  796.       if (exported_p (list) && !invisible_p (list))
  797.     {
  798.       char *value, *named_function_string ();
  799.  
  800.       if (list->function && !hack_it_twice)
  801.         {
  802.           value =
  803.         named_function_string ((char *)NULL,
  804.                        (COMMAND *)list->function, 0);
  805.           hack_it_twice++;
  806.         }
  807.       else
  808.         {
  809.           value = list->value;
  810.           hack_it_twice = 0;
  811.         }
  812.  
  813.       if (value)
  814.         {
  815.           array[count] =
  816.         (char *)xmalloc (2 + strlen (list->name) + strlen (value));
  817.           sprintf (array[count], "%s=%s", list->name, value);
  818.           count++;
  819.         }
  820.     }
  821.  
  822.       if (!hack_it_twice)
  823.     list = list->next;
  824.     }
  825.   array[count] = (char *)NULL;
  826.   return (array);
  827. }
  828.  
  829. /* Add STRING to the array of foo=bar strings that we already
  830.    have to add to the environment.  */
  831. assign_in_env (string)
  832.      char *string;
  833. {
  834.   int size;
  835.  
  836.   int offset = assignment (string);
  837.   char *name = savestring (string);
  838.   char *temp, *value = (char *)NULL;
  839.  
  840.   if (name[offset] == '=')
  841.     {
  842.       char *tilde_expand (), *string_list ();
  843.       WORD_LIST *list, *expand_string ();
  844.       extern int disallow_filename_globbing;
  845.  
  846.       name[offset] = 0;
  847.       temp = name + offset + 1;
  848.       if (!disallow_filename_globbing)
  849.     temp = tilde_expand (temp);
  850.       else
  851.     temp = savestring (temp);
  852.  
  853.       list = expand_string (temp, 0);
  854.       value = string_list (list);
  855.  
  856.       if (list)
  857.     free (list);
  858.  
  859.       free (temp);
  860.     }
  861.  
  862.   if (!value) value = savestring ("");
  863.  
  864.   temp = (char *)xmalloc (2 + strlen (name) + strlen (value));
  865.   sprintf (temp, "%s=%s", name, value);
  866.   free (name);
  867.  
  868.   if (!temporary_env)
  869.     {
  870.       temporary_env = (char **)xmalloc (sizeof (char *));
  871.       temporary_env [0] = (char *)NULL;
  872.     }
  873.  
  874.   size = array_len (temporary_env);
  875.   temporary_env =
  876.     (char **)xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
  877.  
  878.   temporary_env[size] = (temp);
  879.   temporary_env[size + 1] = (char *)NULL;
  880.   array_needs_making = 1;
  881. }
  882.  
  883. /* Find a variable in the temporary environment that is named NAME.
  884.    Return a consed variable, or NULL if not found. */
  885. SHELL_VAR *
  886. find_tempenv_variable (name)
  887.      char *name;
  888. {
  889.   register int i, l = strlen (name);
  890.  
  891.   if (!temporary_env)
  892.     return ((SHELL_VAR *)NULL);
  893.  
  894.   for (i = 0; temporary_env[i]; i++)
  895.     {
  896.       if (strncmp (temporary_env[i], name, l) == 0 &&
  897.       temporary_env[i][l] == '=')
  898.     {
  899.       SHELL_VAR *temp = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  900.  
  901.       temp->next = (SHELL_VAR *)NULL;
  902.       temp->name = savestring (name);
  903.       if (temporary_env[i][l + 1])
  904.         temp->value = savestring (&temporary_env[i][l + 1]);
  905.       else
  906.         temp->value = savestring ("");
  907.       temp->function = (char *)NULL;
  908.       temp->attributes = att_exported;
  909.       temp->context = 0;
  910.       temp->prev_context = (SHELL_VAR *)NULL;
  911.  
  912.       return (temp);
  913.     }
  914.     }
  915.   return ((SHELL_VAR *)NULL);
  916. }
  917.  
  918. /* Free the storage used in the variable array for temporary
  919.    environment variables. */
  920. dispose_used_env_vars ()
  921. {
  922.   if (!temporary_env)
  923.     return;
  924.  
  925.   free_array (temporary_env);
  926.   temporary_env = (char **)NULL;
  927.   array_needs_making = 1;
  928. }
  929.  
  930. /* Stupid comparison routine for qsort () ing strings. */
  931. qsort_string_compare (s1, s2)
  932.      register char **s1, **s2;
  933. {
  934.   return (strcmp (*s1, *s2));
  935. }
  936.  
  937. /* Add ASSIGN to ARRAY, or supercede a previous assignment in the
  938.    array with the same left-hand side.  Return the new array. */
  939. char **
  940. add_or_supercede (assign, array)
  941.      char *assign;
  942.      register char **array;
  943. {
  944.   register int i;
  945.   int equal_offset = assignment (assign);
  946.  
  947.   if (!equal_offset)
  948.     return (array);
  949.   
  950.   for (i = 0; array[i]; i++)
  951.     {
  952.       if (strncmp (assign, array[i], equal_offset + 1) == 0)
  953.     {
  954.       free (array[i]);
  955.       array[i] = savestring (assign);
  956.       return (array);
  957.     }
  958.     }
  959.   array = (char **)xrealloc (array, (2 + array_len (array)) * sizeof (char *));
  960.   array[i++] = savestring (assign);
  961.   array[i] = (char *)NULL;
  962.   return (array);
  963. }
  964.  
  965. /* Make the environment array for the command about to be executed.  If the
  966.    array needs making.  Otherwise, do nothing.  If a shell action could
  967.    change the array that commands receive for their environment, then the
  968.    code should `array_needs_making++'. */
  969. maybe_make_export_env ()
  970. {
  971.   register int i;
  972.   register char **temp_array;
  973.  
  974.   if (array_needs_making)
  975.     {
  976.       if (export_env)
  977.     free_array (export_env);
  978.  
  979. #ifdef SHADOWED_ENV
  980.       export_env =
  981.     (char **)xmalloc ((1 + array_len (shell_environment)) * sizeof (char *));
  982.  
  983.       for (i = 0; shell_environment[i]; i++)
  984.     export_env[i] = savestring (shell_environment[i]);
  985.       export_env[i] = (char *)NULL;
  986.  
  987. #else /* !SHADOWED_ENV */
  988.  
  989.       export_env = (char **)xmalloc (sizeof (char *));
  990.       export_env[0] = (char *)NULL;
  991.  
  992. #endif /* SHADOWED_ENV */
  993.  
  994.       temp_array = make_var_array (variable_list);
  995.       for (i = 0; temp_array[i]; i++)
  996.     export_env = add_or_supercede (temp_array[i], export_env);
  997.       free_array (temp_array);
  998.  
  999.       if (temporary_env)
  1000.     {
  1001.       for (i = 0; temporary_env[i]; i++)
  1002.         export_env = add_or_supercede (temporary_env[i], export_env);
  1003.  
  1004.       /* Sort the array alphabetically. */
  1005.       qsort (export_env, array_len (export_env),
  1006.          sizeof (char *), qsort_string_compare);
  1007.     }
  1008.       array_needs_making = 0;
  1009.     }
  1010. }
  1011.  
  1012. /* We supply our own version of getenv () because we want library routines
  1013.    to get the changed values of exported variables. */
  1014. char *last_tempenv_value = (char *)NULL;
  1015.  
  1016. char *
  1017. getenv (name)
  1018.      char *name;
  1019. {
  1020.   SHELL_VAR *var = find_tempenv_variable (name);
  1021.  
  1022.   if (var)
  1023.     {
  1024.       if (last_tempenv_value)
  1025.     free (last_tempenv_value);
  1026.       
  1027.       last_tempenv_value = savestring (value_cell (var));
  1028.       dispose_variable (var);
  1029.       return (last_tempenv_value);
  1030.     }
  1031.   else
  1032.     {
  1033.       var = find_variable (name);
  1034.       if (var && exported_p (var))
  1035.     return (value_cell (var));
  1036.     }
  1037.   return ((char *)NULL);
  1038. }
  1039.